home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / C / Games / Xconq 7.1.0 / src / xconq-7.1.0 / x11 / xhelp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-07-07  |  11.5 KB  |  398 lines  |  [TEXT/R*ch]

  1. /* Help for the X11 interface to Xconq.
  2.    Copyright (C) 1991, 1992, 1993, 1994, 1995 Stanley T. Shebs.
  3.  
  4. Xconq is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2, or (at your option)
  7. any later version.  See the file COPYING.  */
  8.  
  9. #include "conq.h"
  10. #include "xconq.h"
  11. void update_help PARAMS ((Side *side));
  12.  
  13. /* (should go to ui.h?  and node stack code too?) */
  14. #define NODESTACKSIZE 100
  15.  
  16. static void describe_map PARAMS ((int arg, char *key, char *buf));
  17.  
  18. static void help_next_callback PARAMS ((Widget w, XtPointer client_data,
  19.                        XtPointer call_data));
  20. static void help_prev_callback PARAMS ((Widget w, XtPointer client_data,
  21.                        XtPointer call_data));
  22. static void help_back_callback PARAMS ((Widget w, XtPointer client_data,
  23.                        XtPointer call_data));
  24. static void help_close_callback PARAMS ((Widget w, XtPointer client_data,
  25.                         XtPointer call_data));
  26. static void interp_help_command PARAMS ((Side *side, int ch));
  27. static void jump_to_help_node PARAMS ((Side *side, int i));
  28.  
  29. static void help_topic_callback PARAMS ((Widget w, XtPointer dummy,
  30.                     XawListReturnStruct *list));
  31.  
  32. static char **nodetitles;
  33.  
  34. static void
  35. describe_map(arg, key, buf)
  36. int arg;
  37. char *key, *buf;
  38. {
  39. #define SCB(s) strcat(buf,s)
  40.     SCB("In move mode:\n");
  41.     SCB("  The next unit that can do anything will be selected automatically.\n");
  42.     SCB("  Left-click on a destination to move the selected unit there.\n");
  43.     SCB("  To select a unit, center-click it.\n");
  44.     SCB("\n");
  45.     SCB("In look mode:\n");
  46.     SCB("  Left-click on a unit to make the current one.\n");
  47.     SCB("  To move it, right-click, use 'm'ove command or 'z' to switch back ");
  48.     SCB("to move mode.\n");
  49.     SCB("\n");
  50.     SCB("In design mode:\n");
  51.     SCB("  Left-click to perform the tool-specific action: add unit or paint ");
  52.     SCB("terrain, population, or feature.\n");
  53.     SCB("  Shift-left-click to perform the tool-specific current object ");
  54.     SCB("selection: pick current unit type, terrain type, side, or feature.\n");
  55.     SCB("\n");
  56.     SCB("In any mode:\n");
  57.     SCB("  Center-click on a unit or cell to make the current one.\n");
  58.     SCB("  Drag-shift-center-click to measure distance (gasp! hold down Shift, ");
  59.     SCB("press center button at origin, drag to destination, release button ");
  60.     SCB("and Shift).\n");
  61.     SCB("  Right-click on a destination to move the selected unit there.\n");
  62.     SCB("  Move the mouse while holding Meta to change the current cell.\n");
  63.     SCB("  Press a keypad key to scroll the look.\n");
  64. #undef SCB
  65. }
  66.  
  67. static void 
  68. help_topic_callback (w, dummy, list)
  69. Widget w;
  70. XtPointer dummy;
  71. XawListReturnStruct *list;
  72. {
  73.     Side *side;
  74.  
  75.     if (!find_side_via_widget(w, &side))
  76.       return;
  77.  
  78.     jump_to_help_node(side, list->list_index);
  79. }
  80.  
  81. static void 
  82. jump_to_help_node(side, i)
  83. Side *side;
  84. int i;
  85. {
  86.     i = i % side->ui->nodenumber;
  87.     if (i < 0)
  88.       i += side->ui->nodenumber;
  89.     XawListHighlight(side->ui->help_topicList, i);
  90.     side->ui->curhelpnode = side->ui->nodestack[i];
  91.     side->ui->nodestackpos = i;
  92.     update_help(side);
  93. }
  94.  
  95. void
  96. create_help(side)
  97. Side *side;
  98. {
  99.     int i;
  100.     HelpNode *hnp;
  101.  
  102.     add_help_node("map", describe_map, 0, first_help_node);
  103.  
  104.     /* initialize node stack */
  105.     if (side->ui->nodestack == NULL)
  106.       side->ui->nodestack =
  107.     (HelpNode **) xmalloc(1000 * sizeof(HelpNode *));
  108.  
  109.     for (i = 0, hnp = first_help_node;
  110.      hnp && (hnp != first_help_node || i == 0); hnp = hnp->next) {
  111.     side->ui->nodestack[i++] = hnp;
  112.     }
  113.     side->ui->nodenumber = i;
  114.  
  115.     nodetitles = (char **) xmalloc((side->ui->nodenumber+1)*sizeof(char *));
  116.     for (i=0; i<side->ui->nodenumber; i++) {
  117.     nodetitles[i] = side->ui->nodestack[i]->key;
  118.     }
  119.     nodetitles[side->ui->nodenumber] = NULL;
  120.  
  121. #if 0
  122.     /* useless with widgetified help, use resource file to change defaults */
  123.  
  124.     side->ui->helpw = 500;  side->ui->helph = 700;
  125.     if ( 0 /* !empty_string(geospec) */) {
  126.     /* This map has been given a preferred size - work to it. */
  127.     flags = XParseGeometry(geospec, &sx, &sy, &w, &h);
  128.     if (flags & WidthValue)
  129.       side->ui->helpw = w;
  130.     if (flags & HeightValue)
  131.       side->ui->helph = h;
  132.     /* Note that we allow the caller to specify geometries
  133.        that may be larger than the available screen, on the
  134.        theory that people specifying geometries explicitly
  135.        know what they're doing. */
  136.     } else {
  137.         int w, h;
  138.  
  139.     /* Shrink to fit display if the default is too big. */
  140.     w = DisplayWidth(side->ui->dpy, side->ui->screen);
  141.     h = DisplayHeight(side->ui->dpy, side->ui->screen);
  142.     /* Leave a little room around the edges, but not too much;
  143.        Xconq help needs all the screen space it can get. */
  144.     side->ui->helpw = min(side->ui->helpw, w - w / 16);
  145.     side->ui->helph = min(side->ui->helph, h - h / 16);
  146.     }
  147. #endif
  148.  
  149.     side->ui->help_shell =
  150.       XtVaCreatePopupShell("helpShell", topLevelShellWidgetClass,
  151.                side->ui->shell,  NULL);
  152.     side->ui->help_form = 
  153.       XtVaCreateManagedWidget("form", formWidgetClass,
  154.                   side->ui->help_shell,  NULL);
  155.  
  156.     side->ui->help_title =
  157.       XtVaCreateManagedWidget("title", labelWidgetClass, side->ui->help_form,
  158.                   XtNlabel, "",
  159.                   XtNtop,    XawChainTop, 
  160.                   XtNbottom, XawChainTop, 
  161.                   XtNleft,   XawChainLeft, 
  162.                   XtNright,  XawChainRight, 
  163.                   NULL);
  164.  
  165.     side->ui->help_topicPort =
  166.       XtVaCreateManagedWidget("topicPort", viewportWidgetClass,
  167.                   side->ui->help_form,
  168.                   XtNallowVert, True,
  169.                   XtNfromVert, side->ui->help_title,
  170.                   XtNtop,    XawChainTop, 
  171.                   XtNbottom, XawChainBottom, 
  172.                   XtNleft,   XawChainLeft, 
  173.                   XtNright,  XawChainLeft, 
  174.                   NULL);
  175.  
  176.     side->ui->help_topicList =
  177.       XtVaCreateManagedWidget("topicList", listWidgetClass,
  178.                   side->ui->help_topicPort,
  179.                   XtNbottom, XawChainTop, 
  180.                   XtNverticalList, True,
  181.                   XtNforceColumns, True,
  182.                   XtNdefaultColumns, 1,
  183.                   NULL);
  184.     XawListChange(side->ui->help_topicList,
  185.           nodetitles, side->ui->nodenumber, 0, True);
  186.     XtAddCallback(side->ui->help_topicList, XtNcallback,
  187.           (XtCallbackProc) help_topic_callback, (XtPointer) NULL);
  188.  
  189.     side->ui->help_text =
  190.       XtVaCreateManagedWidget("text", asciiTextWidgetClass, side->ui->help_form,
  191.                   XtNdisplayCaret, False,
  192.                   XtNeditType, XawtextRead,
  193. /*                  XtNscrollHorizontal, XawtextScrollWhenNeeded, */
  194.                   XtNscrollVertical, XawtextScrollAlways,
  195.                   XtNwrap, XawtextWrapWord,
  196.                   XtNfromVert,  side->ui->help_title,
  197.                   XtNfromHoriz, side->ui->help_topicPort,
  198.                   XtNtop,    XawChainTop, 
  199.                   XtNbottom, XawChainBottom, 
  200.                   XtNleft,   XawChainLeft, 
  201.                   XtNright,  XawChainRight, 
  202.                   NULL);
  203.  
  204.     side->ui->help_next =
  205.       XtVaCreateManagedWidget("next", commandWidgetClass, side->ui->help_form,
  206.                   XtNlabel, "Next",
  207.                   XtNfromVert, side->ui->help_text,
  208.                   XtNtop,    XawChainBottom, 
  209.                   XtNbottom, XawChainBottom, 
  210.                   XtNleft,   XawChainLeft, 
  211.                   XtNright,  XawChainLeft, 
  212.                   NULL);
  213.     XtAddCallback(side->ui->help_next, XtNcallback, help_next_callback, NULL);
  214.     side->ui->help_prev =
  215.       XtVaCreateManagedWidget("prev", commandWidgetClass, side->ui->help_form,
  216.                   XtNlabel, "Prev",
  217.                   XtNfromHoriz, side->ui->help_next,
  218.                   XtNfromVert,  side->ui->help_text,
  219.                   XtNtop,    XawChainBottom, 
  220.                   XtNbottom, XawChainBottom, 
  221.                   XtNleft,   XawChainLeft, 
  222.                   XtNright,  XawChainLeft, 
  223.                   NULL);
  224.     XtAddCallback(side->ui->help_prev, XtNcallback, help_prev_callback, NULL);
  225.     side->ui->help_back =
  226.       XtVaCreateManagedWidget("back", commandWidgetClass, side->ui->help_form,
  227.                   XtNlabel, "Back",
  228.                   XtNfromHoriz, side->ui->help_prev,
  229.                   XtNfromVert,  side->ui->help_text,
  230.                   XtNtop,    XawChainBottom, 
  231.                   XtNbottom, XawChainBottom, 
  232.                   XtNleft,   XawChainLeft, 
  233.                   XtNright,  XawChainLeft, 
  234.                   NULL);
  235.     XtAddCallback(side->ui->help_back, XtNcallback, help_back_callback, NULL);
  236.     side->ui->help_close =
  237.       XtVaCreateManagedWidget("close", commandWidgetClass, side->ui->help_form,
  238.                   XtNlabel, "Close",
  239.                   XtNfromHoriz, side->ui->help_back,
  240.                   XtNfromVert,  side->ui->help_text,
  241.                   XtNtop,    XawChainBottom, 
  242.                   XtNbottom, XawChainBottom, 
  243.                   XtNleft,   XawChainLeft, 
  244.                   XtNright,  XawChainLeft, 
  245.                   NULL);
  246.     XtAddCallback(side->ui->help_close, XtNcallback, help_close_callback, NULL);
  247.  
  248.     XtRealizeWidget(side->ui->help_shell);
  249.  
  250.     /* which is the most useful help page to display at startup? */
  251.     jump_to_help_node (side, 2);
  252. }
  253.  
  254. static void 
  255. help_next_callback(w, client_data, call_data)
  256. Widget w;
  257. XtPointer client_data;
  258. XtPointer call_data;
  259. {
  260.     Side *side;
  261.  
  262.     if (find_side_via_widget(w, &side)) {
  263.     interp_help_command(side, 'n');
  264.     }
  265. }
  266.  
  267. static void 
  268. help_prev_callback(w, client_data, call_data)
  269. Widget w;
  270. XtPointer client_data;
  271. XtPointer call_data;
  272. {
  273.     Side *side;
  274.  
  275.     if (find_side_via_widget(w, &side)) {
  276.     interp_help_command(side, 'p');
  277.     }
  278. }
  279.  
  280. static void 
  281. help_back_callback(w, client_data, call_data)
  282. Widget w;
  283. XtPointer client_data;
  284. XtPointer call_data;
  285. {
  286.     Side *side;
  287.  
  288.     if (find_side_via_widget(w, &side)) {
  289.     interp_help_command(side, 'b');
  290.     }
  291. }
  292.  
  293. static void 
  294. help_close_callback(w, client_data, call_data)
  295. Widget w;
  296. XtPointer client_data;
  297. XtPointer call_data;
  298. {
  299.     Side *side;
  300.  
  301.     if (find_side_via_widget(w, &side)) {
  302.     popdown_help(side);
  303.     }
  304. }
  305.  
  306. /* Keyboard command interpretation for the help window. */
  307.  
  308. static void
  309. interp_help_command(side, ch)
  310. Side *side;
  311. int ch;
  312. {
  313.     int i;
  314.  
  315.     switch (ch) {
  316.       case 'n':
  317.         i = side->ui->nodestackpos+1;
  318.         break;
  319.       case 'p':
  320.         i = side->ui->nodestackpos-1;
  321.     break;
  322.       case 'b':
  323.     if (side->ui->nodestackpos <= 0) {
  324.         beep(side);
  325.         return;
  326.     }
  327.     i = side->ui->nodestackpos-1;
  328.     break;
  329.       case 't':
  330.     i = 0;
  331.     break;
  332.       default:
  333.     abort();  /* should never happen */
  334.     }
  335.  
  336.     jump_to_help_node(side, i);
  337. }
  338.  
  339. void
  340. update_help(side)
  341. Side *side;
  342. {
  343.     char *keystr, *helpstr;
  344.  
  345.     if (!side->ui->help_shell)
  346.       return;
  347.     if (side->ui->curhelpnode == NULL)
  348.       return; /* (should never happen?) */
  349.  
  350.     /* Update the topic title widget. */
  351.     keystr = side->ui->curhelpnode->key;
  352.     if (keystr == NULL)
  353.       keystr = "???";
  354.     nargs = 0;
  355.     XtSetArg(tmpargs[nargs], XtNlabel, keystr);  nargs++;
  356.     XtSetValues(side->ui->help_title, tmpargs, nargs);
  357.  
  358.     /* Update the help info proper. */
  359.     helpstr = get_help_text(side->ui->curhelpnode);
  360.     if (helpstr == NULL)
  361.       helpstr = "???";
  362.     /* This shouldn't be necessary, but apparently some text widgets
  363.        go berserk when handed zero-length strings.  (This happens
  364.        on several different platforms.) */
  365.     if (strlen(helpstr) == 0)
  366.       helpstr = " ";
  367.     nargs = 0;
  368.     XtSetArg(tmpargs[nargs], XtNstring, helpstr);  nargs++;
  369.     XtSetArg(tmpargs[nargs], XtNlength, strlen(helpstr));  nargs++;
  370.     XtSetArg(tmpargs[nargs], XtNinsertPosition, 0);  nargs++;
  371.     XtSetValues(side->ui->help_text, tmpargs, nargs);
  372. }
  373.  
  374. void
  375. popup_help(side)
  376. Side *side;
  377. {
  378.     if (!side->ui->help_shell) {
  379.     create_help(side);
  380.     update_help(side);
  381.  
  382.     XSetWMProtocols(side->ui->dpy, XtWindow(side->ui->help_shell),
  383.             &side->ui->kill_atom, 1);
  384.     XtOverrideTranslations(side->ui->help_shell,
  385.         XtParseTranslationTable("<Message>WM_PROTOCOLS: wm-quit()"));
  386.     }
  387.     XtPopup(side->ui->help_shell, XtGrabNone);
  388.     /* Expose event will cause window contents to be drawn now. */
  389. }
  390.  
  391. void
  392. popdown_help(side)
  393. Side *side;
  394. {
  395.     if (side->ui->help_shell)
  396.       XtPopdown(side->ui->help_shell);
  397. }
  398.